package com.rp.article.serivce.impl;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.rp.article.config.RabbitMQDelayConfig;
import com.rp.article.mapper.ArticleMapper;
import com.rp.article.serivce.ArticleService;
import com.rp.bo.NewArticleBO;
import com.rp.news.common.PagedResult;
import com.rp.news.common.ResponseStatusEnum;
import com.rp.news.enums.ArticleAppointType;
import com.rp.news.enums.ArticleReviewLevel;
import com.rp.news.enums.ArticleReviewStatus;
import com.rp.news.enums.YesOrNo;
import com.rp.news.exception.GraceException;
import com.rp.news.util.extent.AliTextReviewUtils;
import com.rp.pojo.Article;
import com.rp.pojo.Category;
import org.springframework.amqp.AmqpException;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageDeliveryMode;
import org.springframework.amqp.core.MessagePostProcessor;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;

import java.util.Date;
import java.util.List;

@Service
public class ArticleServiceImpl implements ArticleService {


    @Autowired
    private ArticleMapper articleMapper;


    @Autowired
    private AliTextReviewUtils aliTextReviewUtils;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Transactional
    @Override
    public void createArticle(NewArticleBO newArticleBO, Category category) {
        String articleId = IdUtil.fastSimpleUUID();

        Article article = Convert.convert(Article.class, newArticleBO);

        article.setId(articleId);
        article.setCategoryId(category.getId());
        article.setArticleStatus(ArticleReviewStatus.REVIEWING.type);
        article.setCommentCounts(0);
        article.setReadCounts(0);

        article.setIsDelete(YesOrNo.NO.type);
        article.setCreateTime(new Date());
        article.setUpdateTime(new Date());

        if (article.getIsAppoint() == ArticleAppointType.TIMING.type) {
            article.setPublishTime(newArticleBO.getPublishTime());
        } else {
            article.setPublishTime(new Date());
        }

        int insert = articleMapper.insert(article);

        if (insert != 1) {
            GraceException.display(ResponseStatusEnum.ARTICLE_CREATE_ERROR);
        }
        //TODO FIXME 发送延迟消息

        //发送延迟消息到mq,计算定时发布时间和当前时间的时间差,则为往后延迟的时间
        if (article.getIsAppoint() == ArticleAppointType.TIMING.type) {

            Date publishTime = newArticleBO.getPublishTime();
            Date nowTime = new Date();

            //int betweenTime = (int)DateUtil.between(nowTime, publishTime, DateUnit.MS);

            //todo
            int betweenTime = 10 * 1000;
            MessagePostProcessor messagePostProcessor = new MessagePostProcessor() {
                @Override
                public Message postProcessMessage(Message message) throws AmqpException {
                    message.getMessageProperties()
                            .setDeliveryMode(MessageDeliveryMode.PERSISTENT);
                    message.getMessageProperties()
                            .setDelay(betweenTime);//单位是毫秒
                    return message;
                }
            };
            rabbitTemplate.convertAndSend(RabbitMQDelayConfig.EXCHANGER_DELAY,
                    "delay.test", articleId, messagePostProcessor);

        }


        //todo 通过阿里智能ai实现对文章文本的自动检测(自动审核)
        String review = aliTextReviewUtils.reviewTextContent(article.getContent());

        review = ArticleReviewLevel.PASS.type;
        if (ArticleReviewLevel.PASS.type.equalsIgnoreCase(review)) {
            //修改当前文章 状态标记为审核通过
            this.updateArticleStatus(articleId, ArticleReviewStatus.SUCCESS.type);
        } else if (ArticleReviewLevel.REVIEW.type.equalsIgnoreCase(review)) {

            //修改当前文章 状态标记为需要人工审核
            this.updateArticleStatus(articleId, ArticleReviewStatus.WAITING_MANUAL.type);


        } else if (ArticleReviewLevel.BLOCK.type.equalsIgnoreCase(review)) {

            //修改当前文章,状态标记为审核未通过
            this.updateArticleStatus(articleId, ArticleReviewStatus.FAILED.type);


        }


    }

    @Transactional
    @Override
    public void updateAppointToPublish() {

        articleMapper.updateAppointToPublish();

    }


    /**
     * 查询我的文章列表
     *
     * @param userId
     * @param keyword
     * @param status
     * @param startDate
     * @param endDate
     * @param page
     * @param pageSize
     * @return
     */
    @Override
    public PagedResult queryMyList(String userId, String keyword, Integer status, Date startDate, Date endDate, Integer page, Integer pageSize) {


        Example example = new Example(Article.class);
        example.orderBy("createTime").desc();
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("publishUserId", userId);

        if (StrUtil.isNotBlank(keyword)) {
            criteria.andLike("title", "%" + keyword + "%");
        }
        if (ArticleReviewStatus.isArticleStatusValid(status)) {
            criteria.andEqualTo("articleStatus", status);
        }

        if (status != null && status == 12) {
            criteria.andEqualTo("articleStatus", ArticleReviewStatus.REVIEWING.type)
                    .orEqualTo("articleStatus", ArticleReviewStatus.WAITING_MANUAL.type);
        }

        criteria.andEqualTo("isDelete", YesOrNo.NO.type);

        if (startDate != null) {
            criteria.andGreaterThanOrEqualTo("publishTime", startDate);
        }
        if (endDate != null) {
            criteria.andLessThanOrEqualTo("publishTime", endDate);
        }

        PageHelper.startPage(page, pageSize);
        List<Article> select = articleMapper.selectByExample(example);


        return setterPageResult(select, page);
    }

    @Override
    public void updateArticleStatus(String articleId, Integer pendingStatus) {
        Example example = new Example(Article.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("id", articleId);
        Article article = new Article();
        article.setArticleStatus(pendingStatus);

        int i = articleMapper.updateByExampleSelective(article, example);
        if (i != 1) {
            GraceException.display(ResponseStatusEnum.ARTICLE_CREATE_ERROR);
        }
    }

    @Override
    public PagedResult queryAllList(Integer status, Integer page, Integer pageSize) {

        Example example = new Example(Article.class);
        example.orderBy("createTime").desc();
        Example.Criteria criteria = example.createCriteria();
        if (ArticleReviewStatus.isArticleStatusValid(status)) {
            criteria.andEqualTo("articleStatus", status);
        }

        if (status != null && status == 12) {
            criteria.andEqualTo("articleStatus", ArticleReviewStatus.REVIEWING.type)
                    .orEqualTo("articleStatus", ArticleReviewStatus.WAITING_MANUAL.type);
        }

        criteria.andEqualTo("isDelete", YesOrNo.NO.type);

        PageHelper.startPage(page, pageSize);
        List<Article> select = articleMapper.selectByExample(example);

        return setterPageResult(select, page);
    }

    @Override
    @Transactional
    public void deleteArticle(String userId, String articleId) {
        Example example = new Example(Article.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("publishUserId", userId);
        criteria.andEqualTo("id", articleId);
        Article article = new Article();
        article.setIsDelete(YesOrNo.YES.type);
        int i = articleMapper.updateByExampleSelective(article, example);

        if (i != 1) {
            GraceException.display(ResponseStatusEnum.ARTICLE_DELETE_ERROR);
        }
    }

    @Override
    @Transactional
    public void withdrawArticle(String userId, String articleId) {
        Example example = new Example(Article.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("publishUserId", userId);
        criteria.andEqualTo("id", articleId);
        Article article = new Article();
        article.setArticleStatus(ArticleReviewStatus.WITHDRAW.type);
        int i = articleMapper.updateByExampleSelective(article, example);

        if (i != 1) {
            GraceException.display(ResponseStatusEnum.ARTICLE_WITHDRAW_ERROR);
        }
    }

    @Override
    public void updateArticleToGridFS(String articleId, String articleMongoId) {
        Article aritcle = new Article();
        aritcle.setId(articleId);
        aritcle.setMongoFileId(articleMongoId);
        articleMapper.updateByPrimaryKeySelective(aritcle);
    }


    private PagedResult setterPageResult(List<?> list, Integer page) {
        PageInfo<?> pageInfo = new PageInfo<>(list);
        PagedResult result = new PagedResult();
        result.setPage(page);
        result.setTotal(pageInfo.getPages());
        result.setRecords(pageInfo.getTotal());
        result.setRows(list);
        return result;
    }
}
